/*
 *  Copyright 2015-2016, RenGu Technology (BeiJing) Co., Ltd.
 *  All right reserved.
 *
 *  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF RENGU TECHNOLOGY (BeiJing) CO., LTD.
 *
 *  THE CONTENTS OF THIS FILE MAY NOT BE DISCLOSED TO THIR PARTIES,
 *  COPIED OR DUPLICATED IN ANY FORM, IN WHOLE OR IN PART,
 *  WITHOUT THE PRIOR WRITTEN PERMISSION OF RENGU TECHNOLOGY (BeiJing) CO., LTD.
 *
 *  VirtAcctSingleAdjustService
 *
 *  Edit History:
 *      lizhangtao Created on 2020年05月13日
 *
 */
package cc.rengu.igas.acct.core.service.trans;

import cc.rengu.igas.acct.common.dao.AcctDetailMapper;
import cc.rengu.igas.acct.common.dao.impl.AcctDetailMapperImpl;
import cc.rengu.igas.acct.common.entity.AcctDetail;
import cc.rengu.igas.acct.common.enums.AcctRespCodeEnum;
import cc.rengu.igas.acct.common.enums.AcctTransStatusEnum;
import cc.rengu.igas.acct.core.service.realize.AcctOpt;
import cc.rengu.igas.acct.facade.request.VirtAcctSingleAdjustRequest;
import cc.rengu.igas.acct.facade.response.VirtAcctSingleAdjustResponse;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.RedisUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.base.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * 虚拟账户单笔记账服务具体实现
 *
 * @author lizhangtao
 * @version 1.0
 * @date 2020/5/8
 */
public class VirtAcctSingleAdjustService extends RadpService {

    @Override
    protected int bizInit(String s) {
        return 0;
    }

    @Override
    protected int bizProcess(String s, int i) {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        try {
            VirtAcctSingleAdjustRequest virtAcctSingleAdjustRequest = new VirtAcctSingleAdjustRequest();
            ConvertUtil.convertOutput(virtAcctSingleAdjustRequest);
            rglog.info("virtAcctSingleAdjustRequest = <{}>", JSONObject.toJSONString(virtAcctSingleAdjustRequest));
            VirtAcctSingleAdjustResponse virtAcctSingleAdjustResponse = new VirtAcctSingleAdjustResponse();
            virtAcctSingleAdjustResponse.setHeader(virtAcctSingleAdjustRequest.getHeader());
            BizResponse<VirtAcctSingleAdjustResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(virtAcctSingleAdjustResponse);
            String acctAdjustSuffix = virtAcctSingleAdjustRequest.getHeader().getTraceNo().length() >= 32 ? virtAcctSingleAdjustRequest.getHeader().getTraceNo().substring(0, 32) : virtAcctSingleAdjustRequest.getHeader().getTraceNo();

            //增加虚拟账户控制记账时，不允许同一笔流水号多次记账
            String virtAcctTraceNoCache = RedisUtil.getAndSet("ACCTADJUST" + acctAdjustSuffix,
                    virtAcctSingleAdjustRequest.getHeader().getTraceNo());
            //认为已经记账
            if (!StringUtil.isNullorEmpty(virtAcctTraceNoCache)) {
                rglog.debug("从缓存中获取数据成功，认为已记账,key = <{}>", "ACCTADJUST" + acctAdjustSuffix);
                //查询返回数据，且同时记账成功，不需要二次记账
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespDesc());
                throw new BizException(AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespCode(), AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespDesc());
            }
            RedisUtil.onceExpire("ACCTADJUST" + acctAdjustSuffix, 60 * 5);
            AcctDetailMapper acctDetailMapper = new AcctDetailMapperImpl();
            AcctDetail acctDetailSelect = acctDetailMapper.selectAcctDetailByFromSeqNumCustomerIdAndUserId(virtAcctSingleAdjustRequest.getUserId(), virtAcctSingleAdjustRequest.getUserType(),
                    virtAcctSingleAdjustRequest.getAcctNo(), virtAcctSingleAdjustRequest.getCustomerId(),
                    virtAcctSingleAdjustRequest.getHeader().getTraceNo().length() >= 32 ? virtAcctSingleAdjustRequest.getHeader().getTraceNo().substring(0, 32) : virtAcctSingleAdjustRequest.getHeader().getTraceNo(),
                    virtAcctSingleAdjustRequest.getHeader().getInstId());
            if (null != acctDetailSelect && "00".equals(acctDetailSelect.getAcctStatus())) {
                //查询返回数据，且同时记账成功，不需要二次记账
                rglog.debug("从数据库中获取数据成功，认为已记账,acctDetailSelect = <{}>", JSON.toJSONString(acctDetailSelect));
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespDesc());
                throw new BizException(AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespCode(), AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespDesc());
            }

            //调用普通借贷记
            AcctDetail acctDetail = new AcctOpt().normal(virtAcctSingleAdjustRequest.getHeader().getTransDate(),
                    virtAcctSingleAdjustRequest.getHeader().getTransTime(), virtAcctSingleAdjustRequest.getHeader().getTxnNum(),
                    virtAcctSingleAdjustRequest.getHeader().getSrcSysId(), virtAcctSingleAdjustRequest.getHeader().getInstId(),
                    virtAcctSingleAdjustRequest.getHeader().getTraceNo(), virtAcctSingleAdjustRequest.getTransAmt(),
                    virtAcctSingleAdjustRequest.getDebitCreditFlag(),
                    virtAcctSingleAdjustRequest.getAcctNo(), virtAcctSingleAdjustRequest.getCustomerId(),
                    virtAcctSingleAdjustRequest.getUserType(), virtAcctSingleAdjustRequest.getUserId(),
                    virtAcctSingleAdjustRequest.getSummary(), rglog);

            virtAcctSingleAdjustResponse.setAfterBalance(acctDetail.getAfterBalance());
            virtAcctSingleAdjustResponse.setAfterAvailableBalance(acctDetail.getAfterAvailableBalance());
            virtAcctSingleAdjustResponse.setAfterFreezeBalance(acctDetail.getAfterFreezeBalance());
            virtAcctSingleAdjustResponse.setAcctDate(acctDetail.getAcctDate());
            virtAcctSingleAdjustResponse.setAcctSeqNum(acctDetail.getAcctSeqNum());
            virtAcctSingleAdjustResponse.setRespCode(OltpRpcdEnum.TRANS_SUCCESS.getRespCode());
            virtAcctSingleAdjustResponse.setRespDesc(OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
            virtAcctSingleAdjustResponse.setTransStatus(AcctTransStatusEnum.SUCC.getStatus());
            bizResponse.setRspSysId(ChannelEnum.ACCT.getChannelType());
            bizResponse.setTransStatus(TransStatusEnum.TRANS_SUCC);
            bizResponse.setRespCode(OltpRpcdEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
            ConvertUtil.convertInput(bizResponse.getResult());

        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE,
                        OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC,
                        OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespDesc());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e));
            }
        }
        return 0;
    }

    @Override
    protected int bizTerminate(String s) {
        return 0;
    }

}
